package com.dhemery.mack.actions.tests;

import java.util.List;

import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.junit.Before;
import org.junit.Test;

import com.dhemery.mack.actions.AddPageAction;
import com.dhemery.mack.actions.AddNodeAction;
import com.dhemery.mack.adapters.ImageDescriptorSource;
import com.dhemery.mack.gui.NodeEditor;
import com.dhemery.mack.model.Folder;
import com.dhemery.mack.model.Node;
import com.dhemery.mack.model.Page;

import static org.junit.Assert.*;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.*;

public class AddPageActionTests {
	private IWorkbenchPage page;
	private TreeViewer viewer;
	private IAdapterFactory factory;
	private ImageDescriptorSource source;
	private SelectionChangedEvent event;
	private StructuredSelection selection;

	@Before
	public void setUp() {
		page = mock(IWorkbenchPage.class);
		viewer = mock(TreeViewer.class);
		factory = mock(IAdapterFactory.class);
		source = mock(ImageDescriptorSource.class);
		event = mock(SelectionChangedEvent.class);
		selection = mock(StructuredSelection.class);
		stub(event.getSelection()).toReturn(selection);
	}

	@Test
	public void startsDisabled() {
		AddNodeAction action = new AddPageAction(null, viewer, null, source);

		assertFalse(action.isEnabled());
	}

	@Test
	public void registersForSelectionChanges() {
		AddNodeAction action = new AddPageAction(null, viewer, null, source);
		
		verify(viewer).addSelectionChangedListener(action);
	}
	
	@Test
	public void enablesWhenSelectionIsOneFolder() {
		Object[] selectedObjects = new Object[] { new Folder() };

		stub(selection.toArray()).toReturn(selectedObjects);

		AddNodeAction action = new AddPageAction(null, viewer, null, source);

		action.selectionChanged(event);

		assertTrue(action.isEnabled());
	}

	@Test
	public void disablesWhenSelectionIsEmpty() {
		Object[] selectedObjects = new Object[0];

		stub(selection.toArray()).toReturn(selectedObjects);

		AddNodeAction action = new AddPageAction(null, viewer, null, source);

		action.selectionChanged(event);

		assertFalse(action.isEnabled());
	}

	@Test
	public void disablesWhenSelectionIsMultipleFolders() {
		Object[] selectedObjects = new Object[] {
				new Page(),
				new Page(),
			};

		stub(selection.toArray()).toReturn(selectedObjects);

		AddNodeAction action = new AddPageAction(null, viewer, null, source);

		action.selectionChanged(event);

		assertFalse(action.isEnabled());
	}

	@Test
	public void addsANewPageToParentFolder() {
		Folder parent = new Folder();
		Object[] selectedObjects = new Object[] { parent };

		stub(selection.toArray()).toReturn(selectedObjects);

		AddNodeAction action = new AddPageAction(page, viewer, factory, source);
		
		action.selectionChanged(event);
		
		action.run();

		List<Node> children = parent.getNodes();
		assertEquals(1, children.size());
		assertTrue(children.get(0) instanceof Page);
	}

	@Test
	public void opensEditorForNewPage() throws PartInitException {
		Folder parent = new Folder();
		IEditorInput input = mock(IEditorInput.class);
		Object[] selectedObjects = new Object[] { parent };

		stub(selection.toArray()).toReturn(selectedObjects);
		stub(factory.getAdapter(isA(Page.class), eq(IEditorInput.class))).toReturn(input);

		AddNodeAction action = new AddPageAction(page, viewer, factory, source);
		
		action.selectionChanged(event);
		
		action.run();
		verify(page).openEditor(same(input), eq(NodeEditor.ID));
	}
}
